package com.enation.app.javashop.core.orderbill.service.impl;

import com.alibaba.fastjson.JSON;
import com.dag.eagleshop.core.account.model.dto.account.AccountDTO;
import com.dag.eagleshop.core.account.model.dto.account.BusinessTransferReqDTO;
import com.dag.eagleshop.core.account.model.dto.account.BusinessTransferRespDTO;
import com.dag.eagleshop.core.account.model.dto.account.TransferReqDTO;
import com.dag.eagleshop.core.account.model.enums.AccountTypeEnum;
import com.dag.eagleshop.core.account.model.enums.TradeSubjectEnum;
import com.dag.eagleshop.core.account.model.enums.TransferTypeEnum;
import com.dag.eagleshop.core.account.service.AccountManager;
import com.enation.app.javashop.core.client.member.ShopClient;
import com.enation.app.javashop.core.distribution.model.dos.DistributionOrderDO;
import com.enation.app.javashop.core.distribution.service.impl.DistributionOrderManagerImpl;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.orderbill.model.dos.BillItem;
import com.enation.app.javashop.core.orderbill.model.dos.OrderSettle;
import com.enation.app.javashop.core.orderbill.model.enums.BillType;
import com.enation.app.javashop.core.orderbill.service.BillItemManager;
import com.enation.app.javashop.core.orderbill.service.SettleAccountsManager;
import com.enation.app.javashop.core.promotion.shetuan.model.dos.ShetuanOrderDO;
import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanOrderManager;
import com.enation.app.javashop.core.shop.model.vo.ShopVO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderDO;
import com.enation.app.javashop.core.trade.order.model.dos.OrderProfitDO;
import com.enation.app.javashop.core.trade.order.model.enums.ShipTypeEnum;
import com.enation.app.javashop.core.trade.order.service.OrderProfitManager;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.util.CurrencyUtil;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.DictUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 结算
 * @author 孙建
 */
@Service
public class SettleAccountsImpl implements SettleAccountsManager {

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport daoSupport;

    @Autowired
    private BillItemManager billItemManager;
    @Autowired
    private ShetuanOrderManager shetuanOrderManager;
    @Autowired
    private ShopClient shopClient;
    @Autowired
    private MemberManager memberManager;
    @Autowired
    private AccountManager accountManager;
    @Autowired
    private DistributionOrderManagerImpl distributionOrderManagerImpl;
    @Autowired
    private OrderProfitManager orderProfitManager;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 订单结算
     */
    @Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void orderSettle(OrderDO orderDO) {
        logger.info("订单结算：" + JSON.toJSON(orderDO).toString());
        Integer orderId = orderDO.getOrderId();
        String orderSn = orderDO.getSn();
        Integer sellerId = orderDO.getSellerId();

        OrderSettle orderSettle = getOrderSettleByOrderId(orderId);
        if(orderSettle != null){
            logger.info("此订单" + orderDO.getSn() + "已结算");
            return;
        }

        List<TransferReqDTO> transferReqList = new ArrayList<>();

        // 查询店铺
        ShopVO shop = shopClient.getShop(sellerId);

        // 查询明细
        BillItem billItem = billItemManager.getModelByOrderSnAndItemType(orderDO.getSn(), BillType.PAYMENT.name());

        // 查询平台账户和收益账户
        AccountDTO platformAccountDTO = accountManager.queryPlatformAccount(AccountTypeEnum.PLATFORM.getIndex());

        // 查询不结算会员列表 下面再结算的时候过滤掉这类会员
        List<Integer> noSettleMemberList = this.queryNoSettleMemberList();

        // 平台收益
        Double platformCommissionMoney = billItem.getPlatformMoney().doubleValue();
        if(platformCommissionMoney > 0){
            TransferReqDTO platformTransferReqDTO = this.buildPlatformTransferReq(platformAccountDTO, platformCommissionMoney, orderSn + "的平台佣金收益");
            transferReqList.add(platformTransferReqDTO);
        }

        // 订单分销金额计算
        DistributionOrderDO distributionOrderDO = distributionOrderManagerImpl.getModelByOrderSn(orderDO.getSn());
        double lv1Money = billItem.getLv1Money().doubleValue();
        double lv2Money = billItem.getLv2Money().doubleValue();
        // 构建一级分销收益转账
        Integer memberIdLv1 = distributionOrderDO.getMemberIdLv1();
        if(memberIdLv1 != null && lv1Money > 0 && !noSettleMemberList.contains(memberIdLv1)){
            if(memberIdLv1 != -1){
                Member lv1Member = memberManager.getModel(memberIdLv1);
                TransferReqDTO lv1MemberTransferReqDTO =  this.buildCommonTransferReq(platformAccountDTO, lv1Member.getAccountMemberId(), lv1Money, TradeSubjectEnum.LV1_LEADER_REVENUE.description(),orderSn + "的团长佣金收益");
                transferReqList.add(lv1MemberTransferReqDTO);
            }else{
                TransferReqDTO platformLeaderTransferReqDTO = this.buildPlatformTransferReq(platformAccountDTO, lv1Money, orderSn + "的平台一级团长佣金收益");
                transferReqList.add(platformLeaderTransferReqDTO);
            }
        }
        // 构建二级分销收益转账
        Integer memberIdLv2 = distributionOrderDO.getMemberIdLv2();
        if(memberIdLv2 != null && lv2Money > 0 && !noSettleMemberList.contains(memberIdLv2)){
            if(memberIdLv2 != -1){
                Member lv2Member = memberManager.getModel(memberIdLv2);
                TransferReqDTO lv2MemberTransferReqDTO =  this.buildCommonTransferReq(platformAccountDTO, lv2Member.getAccountMemberId(), lv2Money, TradeSubjectEnum.LV2_LEADER_REVENUE.description(),orderSn + "的团长佣金收益");
                transferReqList.add(lv2MemberTransferReqDTO);
            }else{
                TransferReqDTO platformLeaderTransferReqDTO = this.buildPlatformTransferReq(platformAccountDTO, lv2Money, orderSn + "的平台二级团长佣金收益");
                transferReqList.add(platformLeaderTransferReqDTO);
            }
        }
        // 构建邀请人收益转账
        Integer inviterMemberId = distributionOrderDO.getInviterMemberId();
        double inviteMoney = distributionOrderDO.getInviteRebate();
        if(inviterMemberId != null && inviteMoney > 0 && !noSettleMemberList.contains(inviterMemberId)){
            Member inviterMember = memberManager.getModel(inviterMemberId);
            if(inviterMember != null){
                TransferReqDTO inviterTransferReqDTO =  this.buildCommonTransferReq(platformAccountDTO, inviterMember.getAccountMemberId(), inviteMoney, TradeSubjectEnum.INVITE_REVENUE.description(),orderSn + "邀请佣金收益");
                transferReqList.add(inviterTransferReqDTO);
            }
        }
        // 构建补贴转账
        Integer subsidyMemberId = distributionOrderDO.getSubsidyMemberId();
        BigDecimal subsidyMoney = billItem.getSubsidyMoney();
        if(subsidyMemberId != null && subsidyMoney != null && subsidyMoney.doubleValue() > 0 && !noSettleMemberList.contains(subsidyMemberId)){
            Member subsidyMember = memberManager.getModel(subsidyMemberId);
            TransferReqDTO subsidyMemberTransferReqDTO =  this.buildCommonTransferReq(platformAccountDTO, subsidyMember.getAccountMemberId(), subsidyMoney.doubleValue(), TradeSubjectEnum.SUBSIDY_REVENUE.description(), orderSn + "的平台补贴");
            transferReqList.add(subsidyMemberTransferReqDTO);
        }
        // 自提点收益
        double leaderMoney = billItem.getLeaderMoney().doubleValue();
        ShetuanOrderDO shetuanOrderDO = shetuanOrderManager.getByOrderId(orderId);
        if(shetuanOrderDO != null && orderDO.getShippingType().equals(ShipTypeEnum.SELF.getIndex()) && leaderMoney > 0){
            Integer leaderMemberId = shetuanOrderDO.getLeaderMemberId();
            Member leaderMember = memberManager.getModel(leaderMemberId);
            if(leaderMember != null && !noSettleMemberList.contains(leaderMemberId)){
                TransferReqDTO leaderTransferReqDTO = this.buildCommonTransferReq(platformAccountDTO, leaderMember.getAccountMemberId(), leaderMoney, "提成结算",orderSn + "服务佣金收益");
                transferReqList.add(leaderTransferReqDTO);
            }
        }

        // 构建卖家收益转账
        Integer sellerMemberId = shop.getMemberId();
        Member sellerMember = memberManager.getModel(sellerMemberId);
        double sellerSettleMoney = billItem.getSellerMoney().doubleValue();
        TransferReqDTO sellerTransferReqDTO =  this.buildCommonTransferReq(platformAccountDTO, sellerMember.getAccountMemberId(), sellerSettleMoney, TradeSubjectEnum.SELLER_REVENUE.description(),orderSn + "的订单收入");
        transferReqList.add(sellerTransferReqDTO);

        // 发起订单结算业务转账
        BusinessTransferReqDTO businessTransferReqDTO = new BusinessTransferReqDTO();
        businessTransferReqDTO.setTradeVoucherNo(orderDO.getSn());
        businessTransferReqDTO.setTransferReqList(transferReqList);
        businessTransferReqDTO.setOperatorId("1");
        businessTransferReqDTO.setOperatorName("系统");
        logger.info("发起转账:" + JSON.toJSON(businessTransferReqDTO).toString());
        BusinessTransferRespDTO businessTransferRespDTO = accountManager.businessTransfer(businessTransferReqDTO);
        logger.info("转账结果:" + JSON.toJSON(businessTransferRespDTO).toString());

        // 保存结算单项的状态
        billItem.setBillId(0); // 0表示没有结算单
        billItem.setStatus(66); // 66表示已结算
        billItemManager.edit(billItem, billItem.getId());

        // 保存结算记录
        orderSettle = new OrderSettle();
        orderSettle.setOrderId(orderId);
        orderSettle.setOrderSn(orderDO.getSn());
        orderSettle.setSettleTime(DateUtil.getDateline());
        orderSettle.setBillItemId(billItem.getId());
        addOrderSettle(orderSettle);

        // 保存收益结算
        List<OrderProfitDO> orderProfitList = orderProfitManager.listByOrderId(orderId);
        if(orderProfitList != null && orderProfitList.size() > 0){
            for (OrderProfitDO orderProfitDO : orderProfitList) {
                orderProfitDO.setPayTime(DateUtil.getDateline());
                // 没有结算的打上标记
                if(noSettleMemberList.contains(orderProfitDO.getMemberId())){
                    orderProfitDO.setRemark("noSettle");
                }
                orderProfitManager.edit(orderProfitDO);
            }
        }
        logger.info("订单结算完成:" + JSON.toJSON(orderSettle).toString());
    }


    @Override
    public OrderSettle getOrderSettleByOrderId(Integer orderId) {
        String sql = "select * from es_order_settle where order_id = ?";
        return daoSupport.queryForObject(sql, OrderSettle.class, orderId);
    }

    @Override
    public OrderSettle getOrderSettleByOrderSn(String orderSn) {
        String sql = "select * from es_order_settle where order_sn = ?";
        return daoSupport.queryForObject(sql, OrderSettle.class, orderSn);
    }

    @Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void addOrderSettle(OrderSettle orderSettle) {
        daoSupport.insert(orderSettle);
    }


    @Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateOrderSettle(OrderSettle orderSettle, Integer id) {
        daoSupport.update(orderSettle, id);
    }


    /**
     * 计算平台佣金
     */
    @Override
    public BigDecimal countPlatformCommissionMoney(ShopVO shop, Double totalOrderMoney) {
        Double shopCommission = shop.getShopCommission();
        shopCommission = shopCommission == null ? 0.00 : shopCommission;
        Double shopCommissionRate = CurrencyUtil.div(shopCommission, 100);
        Double platformCommissionMoney = CurrencyUtil.mul(totalOrderMoney, shopCommissionRate);
        return BigDecimal.valueOf(platformCommissionMoney);
    }


    /**
     * 构建平台收益转账请求
     */
    private TransferReqDTO buildPlatformTransferReq(AccountDTO platformAccountDTO, double money, String tradeContent){
        TransferReqDTO platformTransferReqDTO = new TransferReqDTO();
        platformTransferReqDTO.setDraweeMemberId(platformAccountDTO.getMemberId());
        platformTransferReqDTO.setDraweeAccountType(platformAccountDTO.getAccountType());
        platformTransferReqDTO.setPayeeMemberId(platformAccountDTO.getMemberId());
        platformTransferReqDTO.setPayeeAccountType(AccountTypeEnum.PROFIT.getIndex());
        platformTransferReqDTO.setAmount(BigDecimal.valueOf(money));
        platformTransferReqDTO.setTradeSubject(TradeSubjectEnum.PLATFORM_REVENUE.description());
        platformTransferReqDTO.setTradeContent(tradeContent);
        platformTransferReqDTO.setTransferType(TransferTypeEnum.AT_ONCE.getIndex());
        return platformTransferReqDTO;
    }


    /**
     * 构建普通会员转账请求
     */
    private TransferReqDTO buildCommonTransferReq(AccountDTO platformAccountDTO, String payeeMemberId, double money, String tradeSubject,String tradeContent){
        TransferReqDTO commonTransferReqDTO = new TransferReqDTO();
        commonTransferReqDTO.setDraweeMemberId(platformAccountDTO.getMemberId());
        commonTransferReqDTO.setDraweeAccountType(platformAccountDTO.getAccountType());
        commonTransferReqDTO.setPayeeMemberId(payeeMemberId);
        commonTransferReqDTO.setPayeeAccountType(AccountTypeEnum.MEMBER_MASTER.getIndex());
        commonTransferReqDTO.setAmount(BigDecimal.valueOf(money));
        commonTransferReqDTO.setTradeSubject(tradeSubject);
        commonTransferReqDTO.setTradeContent(tradeContent);
        commonTransferReqDTO.setTransferType(TransferTypeEnum.AT_ONCE.getIndex());
        return commonTransferReqDTO;
    }

    // 查询不需要结算的会员列表
    private List<Integer> queryNoSettleMemberList(){
        List<Integer> noSettleMemberList = new ArrayList<>();
        try {
            String noSettleMember = DictUtils.getDictValue("", "no_settle_member", "no_settle_member");
            if(StringUtils.isNotEmpty(noSettleMember)){
                String[] noSettleMemberArray = noSettleMember.split(",");
                for (String memberId : noSettleMemberArray) {
                    noSettleMemberList.add(Integer.parseInt(memberId));
                }
            }
        }catch (Exception e){
            logger.error("查询不需要结算的会员列表出错", e);
        }
        return noSettleMemberList;
    }

}
